# 记录漏检框

import numpy as np
import os
import cv2 as cv
from shapely.geometry import Polygon, MultiPoint  # 多边形


iou_thres = 0.5
out_file = 'omitted_targets.txt'
if os.path.exists(out_file):
    os.remove(out_file)


def compute_one_rotation_iou(x_box, y_box):
    # 四边形的二维坐标表示
    xx_box, yy_box = np.array(x_box).reshape(4, 2), np.array(y_box).reshape(4, 2)
    # 构建四边形对象，会自动计算四个点的顺序：左上 左下  右下 右上 左上（返回5个点，最后回到起始点）
    x_poly, y_poly = Polygon(xx_box).convex_hull, Polygon(yy_box).convex_hull

    intersect_area = x_poly.intersection(y_poly).area  # 相交面积
    if intersect_area == 0:
        iou = 0
    else:
        union_area = x_poly.area + y_poly.area - intersect_area  # 总共面积
        iou = intersect_area / union_area
    return iou


def pred_lines2dict(lines_f):
    # 预测结果的字典
    result_dict = {}
    for lll in lines_f:
        lll = lll.split(' ')
        lll[0] = lll[0].split('/')[-1]
        lll[-1] = lll[-1][:-1]
        lll[-8:] = [eval(kk) for kk in lll[-8:]]

        if lll[0] not in result_dict:
            result_dict[lll[0]] = []
            result_dict[lll[0]].append(lll[-8:])
        else:
            result_dict[lll[0]].append(lll[-8:])
    return result_dict


def xywh2xy4(box_in, i_size):
    angle = int(box_in[5])
    cx = i_size * float(box_in[1])
    cy = i_size * float(box_in[2])
    w = i_size * float(box_in[3])
    h = i_size * float(box_in[4])
    arg = ((cx, cy), (w, h), angle)
    box = cv.boxPoints(arg)
    return np.int0(box)


if __name__ == '__main__':
    img_size = 3000
    gt_labels_path = 'D:\\GUANGBRIDGE\\OpticsData\\selected_train_val\\labels\\val\\'
    pred_result_path = 'D:\\GUANGBRIDGE\\OpticsData\\inferences\\inference-exp12-1000without_tiny+1000without_tiny\\results-conf0.1-best-BiCnnNew.txt'
    # 读入预测的结果， 统计预测框的总数量
    with open(pred_result_path, 'r') as fp:
        lines0 = fp.readlines()  # lines0: preds
    pred_nums = len(lines0)
    pred_dict = pred_lines2dict(lines0)
    # 统计预测准确的总数量
    pics_count = 0  # 所有GT中被检测出来的框的个数
    for pic in pred_dict:
        with open(gt_labels_path + pic[:-3] + 'txt', 'r') as fp:
            lines1 = fp.readlines()  # lines1: GTs

        for line_ in lines1:
            line = line_.strip('\n').split(' ')
            line = [eval(kk) for kk in line]
            xy4 = xywh2xy4(line, img_size)  # xy4: one GT box
            count = 0  # A flag representing whether this GT box is detected
            for i in pred_dict[pic]:  # i: one pred box
                iou_result = compute_one_rotation_iou(xy4, i)  # 
                # print(iou_result)
                if iou_result >= iou_thres:
                    count = 1
                    break
            pics_count += count
            if count == 0:
                log_line = ' '.join([pic, line_.strip(), 'omitted'])+'\n'
                with open(out_file, 'a') as fp:
                    fp.write(log_line)

    # 统计真实标签的总数量
    gt_nums = 0
    names_list = [name for name in os.listdir(gt_labels_path) if name.endswith('.txt')]
    for name in names_list:
        with open(gt_labels_path + name, 'r') as fp:
            lines0 = fp.readlines()
        count0 = len(lines0)
        gt_nums += count0
    print("正确预测的个数：", pics_count)
    print("总共预测的个数：", pred_nums)
    print("真实标签的个数：", gt_nums)
    print("检测率： {} %".format((pics_count/gt_nums) * 100))
    print("虚警率： {} %".format(((pred_nums-pics_count)/pred_nums) * 100))
